package xconsole

import (
	"flag"
	"fmt"
	"strings"

	"gitee.com/xiaoyutab/xgotool/xstring"
)

// 根据数据库模型生成对应的Gorm结构文件
//
//	CONSOLE	mkgorm
func mkGorm(help bool) string {
	if help {
		return "根据数据库模型生成对应的Gorm结构文件（目前仅支持mysql数据库）"
	}
	dns := ""   // 数据库DNS连接
	table := "" // 表名称
	model := "" // 所属模型名
	f := ""
	ex := ""
	flag.StringVar(&dns, "dns", "admin:admin@tcp(127.0.0.1:3306)/log_analysis?charset=utf8", "数据库DNS连接配置串")
	flag.StringVar(&table, "table", "logs", "数据库表名称，目前仅支持单表生成")
	flag.StringVar(&model, "model", "model", "所属模型名")
	flag.StringVar(&f, "file", "", "写入到文件中（此处传目录），空表示直接输出到控制台")
	flag.StringVar(&ex, "ex", "", "文件后缀")
	flag.Parse()
	// 数据库连接
	con := connect(dns)
	if con.Error != nil {
		panic(con.Error.Error())
	}
	// 数据表配置
	con.setTable(table)
	if con.Error != nil {
		panic(con.Error.Error())
	}
	mkmodels(con, model, f, ex)
	return ""
}

// 生成model模型
//
//	con		连接信息
//	model	所属模型名
//	f		文件位置
//	ex		文件后缀
func mkmodels(con *gorm_config, model, f, ex string) {
	// 生成model
	c := ""
	c += "package " + model + "\n\n"
	if len(con.TableInfo.Comment) > 0 {
		// 存在表注释
		c += "// " + con.TableInfo.Comment + "\n"
	}
	c += "type " + xstring.CamelCase(con.TableInfo.Name) + " struct {\n"
	// 生成字段
	for _, field := range con.Field {
		fieldName := xstring.CamelCase(field.Field)
		fieldGorm := getFieldGorm(field)
		fieldType := getFiledType(field)
		fieldComment := getFieldComment(field)
		c += "\t" + fieldName + "\t" + fieldType + "\t`" + fieldGorm + "`\t" + fieldComment + "\n"
	}
	c += "}\n\n// 返回所属表名信息\n"
	// 表名注入
	c += "func (c *" + xstring.CamelCase(con.TableInfo.Name) + ") TableName()string{\n\treturn \"" + con.TableInfo.Name + "\"\n}\n\n"
	// 默认信息替换
	maps := map[string]string{
		"tinyint(3)": "tinyint",
		"tinyint(4)": "tinyint",
		"bigint(20)": "bigint",
		"int(11)":    "int",
		"int(10)":    "int",
	}
	for i, v := range maps {
		c = strings.ReplaceAll(c, i, v)
	}
	// 写入到文件中
	if f == "" {
		fmt.Println(c)
	} else if writeFile != nil {
		file_name := f + "/" + con.TableInfo.Name
		if ex != "" {
			file_name += "_" + ex
		}
		file_name += ".go"
		// 写入到文件中
		writeFile(file_name, c)
		fmtFunction(file_name)
	}
}

// 获取字段gorm描述
func getFieldGorm(field Field) string {
	fieldContext := `gorm:"column:` + field.Field
	fieldContext += ";type:" + field.Type
	if field.Key == "PRI" {
		fieldContext = fieldContext + `;primaryKey`
	}
	if field.Key == "UNI" {
		fieldContext = fieldContext + `;unique`
	}
	if field.Extra == "auto_increment" {
		fieldContext = fieldContext + `;autoIncrement`
	}
	if field.Null == "NO" {
		fieldContext = fieldContext + `;not null`
	}
	if field.Comment != "" {
		fieldContext += ";comment:" + field.Comment
	}
	fieldContext += `" form:"` + field.Field + `" json:"` + field.Field + `"`
	return fieldContext
}

// 获取字段类型
func getFiledType(field Field) string {
	typeArr := strings.Split(field.Type, "(")
	typeArr1 := strings.Split(field.Type, ")")

	switch typeArr[0] {
	case "int":
		if typeArr1[1] == " unsigned" {
			return "uint"
		} else {
			return "int"
		}
	case "integer":
		if typeArr1[1] == " unsigned" {
			return "uint"
		} else {
			return "int"
		}
	case "mediumint":
		if typeArr1[1] == " unsigned" {
			return "uint"
		} else {
			return "int"
		}
	case "bit":
		if typeArr1[1] == " unsigned" {
			return "uint"
		} else {
			return "int"
		}
	case "year":
		if typeArr1[1] == " unsigned" {
			return "uint"
		} else {
			return "int"
		}
	case "smallint":
		if typeArr1[1] == " unsigned" {
			return "uint16"
		} else {
			return "int16"
		}
	case "tinyint":
		if typeArr1[1] == " unsigned" {
			return "uint8"
		} else {
			return "int8"
		}
	case "bigint":
		if typeArr1[1] == " unsigned" {
			return "uint64"
		} else {
			return "int64"
		}
	case "decimal":
		return "float64"
	case "double":
		return "float32"
	case "float":
		return "float32"
	case "real":
		return "float32"
	case "numeric":
		return "float32"
	case "timestamp":
		return "string"
	case "datetime":
		return "string"
	case "time":
		return "string"
	case "date":
		return "string"
	default:
		return "string"
	}
}

// 获取字段说明
func getFieldComment(field Field) string {
	if len(field.Comment) > 0 {
		//return "// " + field.Comment
		return "//" + strings.Replace(strings.Replace(field.Comment, "\r", "\\r", -1), "\n", "\\n", -1)
	}
	return ""
}
